package com.sshc625.net {
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLRequestMethod;
	import flash.net.URLVariables;

	import com.sshc625.net.IService;
	import com.sshc625.events.ServiceEvent;

	/**
	 * @author sshc625
	 */
	public class HTTPService extends EventDispatcher implements IService, IEventDispatcher {
		/**
		 * Private properties
		 */
		protected var _loader:URLLoader;
		protected var _request:URLRequest;

		/**
		 * HTTPService
		 * @param       Location of the IServide
		 * @param       [optional]      Method used to send data to IService
		 */
		public function HTTPService( url:String, method:String = URLRequestMethod.POST ):void {
			// Create the URLRequest
			this._request = new URLRequest( url );
			this._request.method = method;

			// Create the Loader
			this._loader = new URLLoader();
			this._loader.addEventListener( Event.COMPLETE, this.onResult );
			this._loader.addEventListener( SecurityErrorEvent.SECURITY_ERROR, this.onFault );
			this._loader.addEventListener( IOErrorEvent.IO_ERROR, this.onFault );
		}

		/**
		 * Executes the IService
		 * @param       [optional] Arguments send to the IService.
		 */
		public function execute( ... args ):void {
			// Add all arguments to the URLRequest
			if ( args.length == 1 ) {
				var myVariables:URLVariables = args[ 0 ] as URLVariables;
				this._request.data = myVariables;
			}

			// Execute
			this._loader.load( this._request );
		}


		/**
		 * Executes when the IService responds succesfully
		 * @param       Event which triggers the method
		 *
		 */
		protected function onResult( event:Event ):void {
			// Close the connection
			this._loader.close();

			// Dispatch event
			var evt:ServiceEvent = new ServiceEvent( ServiceEvent.RESULT );
			evt.result = this._loader.data;
			this.dispatchEvent( evt );

			this.dispose();
		}

		/**
		 * Executes when an error occured while executing the IService
		 * @param       Event which triggers the method
		 *
		 */
		protected function onFault( event:Event ):void {
			// Dispatch event
			if ( this.hasEventListener( ServiceEvent.FAULT )) {
				var evt:ServiceEvent = new ServiceEvent( ServiceEvent.FAULT );
				evt.errorCode = event.type;
				this.dispatchEvent( evt );
			} else {
				// Otherwise throw an error
				throw new Error( event.type + "SERVICE_FAULT" );
			}

			this.dispose();
		}

		/**
		 * Disposes the HTTPService
		 */
		protected function dispose():void {
			this._loader.close();

			// nullify objects
			this._loader = null;
			this._request = null;
		}
	}
}
